package com.carpart.multthread;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.carpart.*;
import com.carpart.bean.CarPart;
import com.carpart.bean.KeyValue;
import com.carpart.util.Configuration;
import com.carpart.util.JdbcUtil;
import com.carpart.util.LOG;

public class Main extends JFrame {

	private static final long serialVersionUID = 1L;
	
	public static Main self;
	public boolean searchStarted = false;
	
	private DataAccess dataAccess = new DataAccess();
	private List<Crawler> crawlers = new ArrayList<Crawler>();
	
	private JTextField yearField = new JTextField("2008");
	private JTextField codeField = new JTextField("91765");
	private JComboBox modelCb = new JComboBox();
	public JComboBox partCb = new JComboBox();
	private JComboBox areaCb = new JComboBox();
	private JComboBox styleCb = new JComboBox();
	private JButton searchBtn = new JButton("提取");
	private JButton filterBtn = new JButton("筛选");
	
	private JTable table;
	private JScrollPane tablePane;
	private DefaultTableModel tableModel;
	private String[] columnTitle = {"更新日期", "部件", "报价", "距离", "分类", "说明", "联系方式"}; //表头
	private int tableMinRow = 22;
	private boolean inited = false;
	private int partIndex = 0;
	private int ThreadTotal = 1; //线程数
	
	public Main() {
		self = this;
	}
	/**
	 * 初始化
	 */
	private void init(){
		this.setTitle("car-part");
		this.setSize(1000, 600); 
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  //关闭窗口的时候，程序退出
		this.setLocationRelativeTo(null);
		this.setLayout(null);
		this.setResizable(false);
		
		JLabel label = new JLabel("品牌");
		label.setBounds(10, 10, 30, 25);
		this.add(label);
		modelCb.setBounds(40, 10, 300, 25);
		
		label = new JLabel("地区");
		label.setBounds(360, 10, 30, 25);
		this.add(label);
		areaCb.setBounds(390, 10, 300, 25);
		
		label = new JLabel("年份");
		label.setBounds(710, 10, 30, 25);
		this.add(label);
		yearField.setBounds(740, 10, 60, 25);
		
		label = new JLabel("邮编");
		label.setBounds(830, 10, 30, 25);
		this.add(label);
		codeField.setBounds(860, 10, 60, 25);
		
		
		label = new JLabel("部件");
		label.setBounds(10, 50, 30, 25);
		this.add(label);
		partCb.setBounds(40, 50, 300, 25);
		partCb.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent arg0) {
				if(inited){
					List<String> list = dataAccess.queryStyle(yearField.getText(), ((KeyValue)modelCb.getSelectedItem()).getKv(), ((KeyValue)areaCb.getSelectedItem()).getKv(), 
															  codeField.getText(), ((KeyValue)partCb.getSelectedItem()).getKv(), "all");
					refreshStyle(list);
				}
			}
		});
		
		label = new JLabel("型号");
		label.setBounds(360, 50, 30, 25);
		this.add(label);
		styleCb.setBounds(390, 50, 300, 25);
		styleCb.addItem(new KeyValue("", "all"));
		
		filterBtn.setBounds(710, 50, 100, 25);
		filterBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				filter();
			}
		});
		
		searchBtn.setBounds(830, 50, 100, 25);
		searchBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(searchStarted){
					stopSearch();
				}else{
					startSearch();
				}
			}
		});
		
		this.add(yearField);
		this.add(codeField);
		this.add(modelCb);
		this.add(partCb);
		this.add(areaCb);
		this.add(styleCb);
		this.add(searchBtn);
		this.add(filterBtn);
		buileTable();
		
//		loadCbData(modelCb, "model.txt");
//		loadCbData(partCb, "part.txt");
//		loadCbData(areaCb, "area.txt");
		
		LogPane logPane = new LogPane();
		JScrollPane scrollPane = new JScrollPane(logPane);
		scrollPane.setBounds(0, 470, 995, 100);
		this.add(scrollPane);
		
		this.setVisible(true); 
		
		LOG.logPane = logPane;
		loadSelectData();
		inited = true;
	}
	
	private void buileTable(){
		Object[][] tableData = new Object[tableMinRow][7];
		for(int i=0; i<tableMinRow; i++){
			tableData[i] = new Object[]{"" , "" , "", "" , "" , "", ""};
		}
		tableModel = new DefaultTableModel(tableData, columnTitle);
		table = new JTable(tableModel){
			private static final long serialVersionUID = 1L;
			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
			public String getToolTipText(MouseEvent e) {   
                int row = table.rowAtPoint(e.getPoint());   
                int col = table.columnAtPoint(e.getPoint());   
                String tipTxt = null;   
                if(row > -1 && col > -1){   
                    Object value = table.getValueAt(row, col);   
                    if(null!=value && !"".equals(value))   
                    	tipTxt = value.toString();
                }   
                return tipTxt;  
			}
        };
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);//关闭表格列自动调整，此时水平滚动条可见 
        
        tablePane = new JScrollPane(table);
        tablePane.setBounds(0, 90, 995, 375);
        this.add(tablePane);  
        refreshTable(new ArrayList<CarPart>());
	}
	
//	private void loadCbData(JComboBox cb, String filename){
//		try{
//			InputStream is = null;
//			try{
//				is = Main.class.getClassLoader().getResourceAsStream(filename);
//			}catch (Exception e) {}
//			if(null == is){
//				is = new FileInputStream(new File(filename));
//			}
//			BufferedReader br = new BufferedReader(new InputStreamReader(is));
//			String line = null;
//			while((line=br.readLine()) != null){
//				String[] arr = line.split("=");
//				KeyValue kv = null;
//				if(arr.length==2){
//					kv = new KeyValue(arr[0], arr[1]);
//				}else{
//					kv = new KeyValue(null, line);
//				}
//				cb.addItem(kv);
//			}
//		}catch (Exception e) {
//			e.printStackTrace();
//		}
//	}
	
	/**
	 * 加载下拉框数据
	 */
	private void loadSelectData(){
		try{
			String filename = "select.xml";
			InputStream is = null;
			try{
				is = Main.class.getClassLoader().getResourceAsStream(filename);
			}catch (Exception e) {}
			if(null == is){
				is = new FileInputStream(new File(filename));
			}
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
			DocumentBuilder builder = factory.newDocumentBuilder(); 
			Document doc = builder.parse(is); 
			
			NodeList nl = doc.getElementsByTagName("model"); 
			for(int i=0; i<nl.getLength(); i++){ 
				Node node = nl.item(i);
				NamedNodeMap map = node.getAttributes();
				if(null!=map.getNamedItem("value") && null!=map.getNamedItem("display")){
					modelCb.addItem(new KeyValue(map.getNamedItem("value").getNodeValue(), map.getNamedItem("display").getNodeValue()));
				}else{
					modelCb.addItem(new KeyValue("", node.getTextContent()));
				}
			}
			
			nl = doc.getElementsByTagName("area"); 
			for(int i=0; i<nl.getLength(); i++){ 
				Node node = nl.item(i);
				NamedNodeMap map = node.getAttributes();
				if(null!=map.getNamedItem("value") && null!=map.getNamedItem("display")){
					areaCb.addItem(new KeyValue(map.getNamedItem("value").getNodeValue(), map.getNamedItem("display").getNodeValue()));
				}else{
					areaCb.addItem(new KeyValue("", node.getTextContent()));
				}
			}
			
			nl = doc.getElementsByTagName("part"); 
			for(int i=0; i<nl.getLength(); i++){ 
				Node node = nl.item(i);
				NamedNodeMap map = node.getAttributes();
				if(null!=map.getNamedItem("value") && null!=map.getNamedItem("display")){
					partCb.addItem(new KeyValue(map.getNamedItem("value").getNodeValue(), map.getNamedItem("display").getNodeValue()));
				}else{
					partCb.addItem(new KeyValue("", node.getTextContent()));
				}
			}
		}catch (Exception e) {
			LOG.error("加载下拉框数据失败。");
			e.printStackTrace();
		}
	}
	
	/**
	 * 检查是否已经准备好了，准备好了才能开始
	 * @return
	 */
	private boolean ready(){
		if(!Configuration.load()){
			return false;
		}
		try{
			//测试是否能链接上数据库
			if(JdbcUtil.init()){
				Connection conn = JdbcUtil.getConnection();
				conn.close();
			}else{
				return false;
			}
		}catch (Exception e) {
			e.printStackTrace();
			LOG.error("获取数据库链接失败，请检查数据库配置文件和数据库是否正常。");
			return false;
		}
		return true;
	}
	
	/**
	 * 开始提取
	 */
	private void startSearch(){
		partIndex = 0;
		searchStarted = true;
		searchBtn.setText("停止");
		try{
			String year = yearField.getText();
			String postCode = codeField.getText();
			String model = ((KeyValue)modelCb.getSelectedItem()).getKv();
			String area = ((KeyValue)areaCb.getSelectedItem()).getKv();
			String part = ((KeyValue)partCb.getSelectedItem()).getKv();
//			String style = ((KeyValue)styleCb.getSelectedItem()).getKv();
			
//			crawler = new Crawler(yearField.getText(), codeField.getText(), "Toyota Camry", partItems, "California");
			dataAccess.init(year, model, area, postCode, part, "all"); //初始化数据库中的数据
			if("all".equals(part)){
				for(int i=0; i<ThreadTotal; i++){ //开多线程
					Crawler crawler = new Crawler(year, postCode, model, part, area);
					crawler.start();
					crawlers.add(crawler);
					try{
						Thread.sleep(1000);
					}catch (Exception e) {}
				}
			}else{
				Crawler crawler = new Crawler(year, postCode, model, part, area);
				crawler.start();
				crawlers.add(crawler);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 停止提取
	 */
	private void stopSearch(){
		searchStarted = false;
		searchBtn.setText("提取");
		for(Crawler crawler : crawlers){
			try{
				crawler.close();
			}catch (Exception e) {}
		}
	}
	
	/**
	 * 筛选数据
	 */
	private void filter(){
		 List<CarPart> list = dataAccess.query(yearField.getText(), codeField.getText(), ((KeyValue)modelCb.getSelectedItem()).getKv(), 
				 								((KeyValue)areaCb.getSelectedItem()).getKv(), ((KeyValue)partCb.getSelectedItem()).getKv(), 
											    (styleCb.getSelectedItem()!=null ? ((KeyValue)styleCb.getSelectedItem()).getKv() : "all"));
		
		 refreshTable(list);
	}
	
	/**
	 * 刷新表格数据
	 * @param list
	 */
	public void refreshTable(List<CarPart> list){
		int len = list.size()>tableMinRow ? list.size() : tableMinRow; 
		Object[][] tableData = new Object[len][7];
		for(int i=0; i<list.size(); i++){
			CarPart carPart = list.get(i);
			tableData[i] = new Object[]{carPart.getYear(), carPart.getPart(), carPart.getPrice(), carPart.getDistMile(), carPart.getStyle(), carPart.getDescription(), carPart.getDealer()};
		}
		
		for(int i=list.size(); i<len; i++){
			tableData[i] =  new Object[]{"" , "" , "", "" , "" , "", ""};
		}
		tableModel.setDataVector(tableData, columnTitle);
		
		DefaultTableCellRenderer render = new DefaultTableCellRenderer();
        render.setHorizontalAlignment(SwingConstants.CENTER);
        
        //调整列
        TableColumn column = table.getColumnModel().getColumn(0);
        column.setMaxWidth(70);
        column.setCellRenderer(render);
        
        
        column = table.getColumnModel().getColumn(1);
        column.setPreferredWidth(200);
        
        render = new DefaultTableCellRenderer();
        render.setHorizontalAlignment(SwingConstants.RIGHT);
        column = table.getColumnModel().getColumn(2);
        column.setMaxWidth(70);
        column.setCellRenderer(render);
        column = table.getColumnModel().getColumn(3);
        column.setMaxWidth(50);
        column.setCellRenderer(render);
        
        column = table.getColumnModel().getColumn(4);
        column.setPreferredWidth(200);
        column = table.getColumnModel().getColumn(5);
        column.setPreferredWidth(200);
        column = table.getColumnModel().getColumn(6);
        column.setPreferredWidth(200);
		
		table.updateUI();
	}
	
	public synchronized String getPart(){
		partIndex++;
		if(partIndex < partCb.getItemCount()){
			return ((KeyValue)Main.self.partCb.getItemAt(partIndex)).getKv();
		}
		return null;
	}
	
	public synchronized void crawlerComplete(Crawler crawler){
		crawlers.remove(crawler);
		crawler.close();
		
		if(crawlers.size() == 0){
			stopSearch();
			
			SwingUtilities.invokeLater(new Runnable() { //事件派发线程中更新ui数据(因为crawlerComplete会被子线程调用)
				@Override
				public void run() {
					String year = yearField.getText();
					String postCode = codeField.getText();
					String model = ((KeyValue)modelCb.getSelectedItem()).getKv();
					String area = ((KeyValue)areaCb.getSelectedItem()).getKv();
					String part = ((KeyValue)partCb.getSelectedItem()).getKv();
					String style = ((KeyValue)styleCb.getSelectedItem()).getKv();
					
					List<String> list = dataAccess.queryStyle(year, model, area, postCode, part, "all");
					refreshStyle(list); //刷新style
					filter(); //刷新数据
				}
			});
		}
	}
	
	/**
	 * 刷新style
	 * @param list
	 */
	public void refreshStyle(List<String> list){
		styleCb.removeAllItems();
		for(String style : list){
			styleCb.addItem(new KeyValue(null, style));
		}
	}
	
	public static void main(String[] args) {
		Main main = new Main();
		main.init();
		main.ready();
	}

}
